package com.zmovie.admin.controller.cinema;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmovie.admin.constant.Constants;
import com.zmovie.admin.controller.vo.CinemaVO;
import com.zmovie.common.error.BusinessException;
import com.zmovie.common.error.EnumBusinessError;
import com.zmovie.common.response.CommonReturnType;
import com.zmovie.common.utils.FileUtils;
import com.zmovie.framework.domain.Cinema;
import com.zmovie.framework.domain.CinemaArea;
import com.zmovie.framework.domain.CinemaBrand;
import com.zmovie.framework.domain.User;
import com.zmovie.framework.service.CinemaAreaService;
import com.zmovie.framework.service.CinemaBrandService;
import com.zmovie.framework.service.CinemaService;
import com.zmovie.framework.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 挚爱之夕
 * @version 1.0
 * @implSpec 电影院信息模块
 * @since 2023-11-30 11:58
 */
@Controller
@RequestMapping("/cinema/info")
@Api(tags = "电影院信息模块")
public class CinemaInfoController {
    @Autowired
    private CinemaService cinemaService;
    @Autowired
    private CinemaBrandService cinemaBrandService;
    @Autowired
    private CinemaAreaService cinemaAreaService;
    @Autowired
    private UserService userService;

    @GetMapping
    @ApiOperation("电影院信息页面")
    public String index(@RequestParam(name = "pageNo", required = false, defaultValue = Constants.PAGE_NO) Integer pageNo,
                        @RequestParam(name = "pageSize", required = false, defaultValue = Constants.PAGE_SIZE) Integer pageSize,
                        Model model) {
        //电影品牌
        List<CinemaBrand> cinemaBrands = cinemaBrandService.listCinemaBrands(new CinemaBrand());
        model.addAttribute(Constants.CINEMA_BRANDS_KEY, cinemaBrands);
        //电影区域
        List<CinemaArea> cinemaAreas = cinemaAreaService.listCinemaAreas(new CinemaArea());
        model.addAttribute(Constants.CINEMA_AREAS_KEY, cinemaAreas);
        //管理员
        List<User> users = userService.listCinemaAdmin();
        model.addAttribute(Constants.USERS_KEY, users);
        //分页查询
        Page<Cinema> cinemaPage = cinemaService.pageCinema(new Cinema(), pageNo, pageSize);
        //转VO
        model.addAttribute(Constants.CINEMA_PAGE_KEY, convert(cinemaPage));
        return "cinema/cinema_info";
    }

    @PostMapping
    @ApiOperation("添加影院")
    @ResponseBody
    @Transactional
    public Object addCinema(@Validated Cinema cinema, @RequestParam(value = "file", required = false) List<MultipartFile> files) {
        try {
            //保存图片
            List<String> fileNameList = FileUtils.saveFile(files, FileUtils.cinemaPath);
            //序列化
            String picture = JSON.toJSONString(fileNameList);
            cinema.setPicture(picture); //图片路径集
            //保存到数据库
            boolean save = cinemaService.save(cinema);
            if (!save) {
                return CommonReturnType.fail("添加失败!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return CommonReturnType.fail("添加失败!");
        }
        return CommonReturnType.success("添加成功!");
    }

    @GetMapping("/{id}")
    @ApiOperation("根据id获取影院信息")
    @ResponseBody
    public Object getCinema(@PathVariable("id") Integer id) {
        return CommonReturnType.success(cinemaService.getById(id));
    }

    @PutMapping
    @ApiOperation("修改影院信息")
    @Transactional
    @ResponseBody
    public Object updateCinema(@Validated Cinema cinema, @RequestParam(value = "file", required = false) List<MultipartFile> files) {
        //先把原来保存的影院图片删掉
        String pictureJson = cinemaService.getById(cinema.getId()).getPicture();
        //反序列化
        List<String> fileNameList = JSON.parseArray(pictureJson, String.class);
        try {
            //删除原来保存的图片
            FileUtils.delete(fileNameList);
        } catch (BusinessException e) {
            e.printStackTrace();
        }
        //保存
        try {
            //保存图片
            fileNameList = FileUtils.saveFile(files, FileUtils.cinemaPath);
            //序列化
            String picture = JSON.toJSONString(fileNameList);
            cinema.setPicture(picture); //图片路径集
            //保存到数据库
            cinemaService.updateById(cinema);
        } catch (Exception e) {
            return CommonReturnType.fail("修改失败!");
        }
        return CommonReturnType.success("修改成功!");
    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除影院信息")
    @ResponseBody
    public Object deleteCinema(@PathVariable("id") @NotNull(message = "id不能为空") Integer id) {
        //先删除保存的图片
        deleteCinemaPicture(id);
        cinemaService.removeById(id);
        return CommonReturnType.success("删除成功!");
    }

    @PostMapping("/search")
    @ApiOperation("分页搜索影院信息")
    public String searchCinema(Cinema cinema,
                               @NotNull(message = "分页页码不能为空") Integer pageNo,
                               @RequestParam(value = "pageSize", required = false, defaultValue = Constants.PAGE_SIZE) Integer pageSize,
                               Model model) {
        Page<Cinema> cinemaPage = cinemaService.pageCinema(cinema, pageNo, pageSize);
        //转VO
        model.addAttribute(Constants.CINEMA_PAGE_KEY, convert(cinemaPage));
        return "cinema/cinema_info :: cinemaList";
    }

    @DeleteMapping
    @ApiOperation("批量删除影院信息")
    @ResponseBody
    public Object deleteCinemaBatch(Integer[] id) throws BusinessException {
        //参数校验
        if (id == null || id.length == 0) {
            throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR);
        }
        //删除图片
        for(Integer i : id){
            deleteCinemaPicture(i);
        }
        cinemaService.removeByIds(Arrays.asList(id));
        return CommonReturnType.success("批量删除成功!");
    }
    @PutMapping("/change")
    @ApiOperation("更改是否可退款、可改签字段")
    @ResponseBody
    public Object change(Cinema cinema) throws BusinessException {
        if(cinema.getId() == null){
            throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR);
        }
        cinemaService.updateByIdCondition(cinema);
        return CommonReturnType.success("修改状态成功!");
    }

    private void deleteCinemaPicture(Integer cinemaId){
        //先把原来保存的影院图片删掉
        String pictureJson = cinemaService.getById(cinemaId).getPicture();
        //反序列化
        List<String> fileNameList = JSON.parseArray(pictureJson, String.class);
        try {
            //删除原来保存的图片
            FileUtils.delete(fileNameList);
        } catch (BusinessException e) {
            e.printStackTrace();
        }
    }
    //转VO
    private Page<CinemaVO> convert(Page<Cinema> cinemaPage) {
        Page<CinemaVO> cinemaVOPage = new Page<>();
        List<Cinema> cinemas = cinemaPage.getRecords();
        //复制
        BeanUtils.copyProperties(cinemaPage, cinemaVOPage);
        List<CinemaVO> cinemaVOList = cinemas.stream().map(this::convert).collect(Collectors.toList());
        cinemaVOPage.setRecords(cinemaVOList);
        return cinemaVOPage;
    }

    private CinemaVO convert(Cinema cinema) {
        //查管理员名称
        User user = userService.getById(cinema.getUserId());
        //查影院地址
        CinemaArea cinemaArea = cinemaAreaService.getById(cinema.getAreaId());
        //查影院品牌
        CinemaBrand cinemaBrand = cinemaBrandService.getById(cinema.getBrandId());
        CinemaVO cinemaVO = new CinemaVO();
        //复制
        BeanUtils.copyProperties(cinema, cinemaVO);
        cinemaVO.setAdminName(user.getUsername());
        cinemaVO.setCinemaArea(cinemaArea);
        cinemaVO.setCinemaBrand(cinemaBrand);
        return cinemaVO;
    }

}
